package com.platform.study.client;

import com.platform.study.client.server_code.com.platform.study.service.api.NetbarServices;
import com.platform.study.client.server_code.com.platform.study.service.api.NetbarServices_Service;
import com.platform.study.client.server_code.com.platform.study.services.dto.User;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Endpoint;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.jaxws.endpoint.dynamic.JaxWsDynamicClientFactory;
import org.apache.cxf.service.model.*;
import org.junit.Test;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;


public class CxfClientTest {
    // 接口地址
    String wsdlAddress = "http://localhost:8002/services/NetbarServices?wsdl";
    /**
     * 方式1.代理类工厂的方式,需要拿到对方的接口
     */
    @Test
    public void cl1() {
        try {
            // 代理工厂
            JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
            // 设置代理地址
            jaxWsProxyFactoryBean.setAddress(wsdlAddress);
            // 设置接口类型
            jaxWsProxyFactoryBean.setServiceClass(NetbarServices.class);
            // 创建一个代理接口实现
            NetbarServices cs = (NetbarServices) jaxWsProxyFactoryBean.create();
            // 数据准备
            User user =setUser();
            // 调用代理接口的方法调用并返回结果
            String result = cs.sayHello(user);
            System.out.println("返回结果:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 动态调用方式
     */
    @Test
    public void cl2() throws Exception {
        // 创建动态客户端
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient(wsdlAddress);
        Object user = Thread.currentThread().getContextClassLoader().loadClass("com.platform.study.services.dto.User").newInstance();
        Method m1 = user.getClass().getMethod("setUsername", String.class);
        Method m2 = user.getClass().getMethod("setEmail", String.class);
        Method m3 = user.getClass().getMethod("setGmtCreate", Date.class);
        Method m4 = user.getClass().getMethod("setUserId", Long.class);
        m1.invoke(user, "yue");
        m2.invoke(user, "777@xxx.com");
        m3.invoke(user, new Date());
        m4.invoke(user, 200L);
        // 需要密码的情况需要加上用户名和密码
        // client.getOutInterceptors().add(new ClientLoginInterceptor(USER_NAME,
        // PASS_WORD));

        // 调用客户端invoke()方法，把inputObject传递给要调用的方法并取得结果对象
        Object[] result =  client.invoke("sayHello", user);
        System.out.println("返回结果:" + result[0]);

    }

    /**
     * wsdl2java http://localhost:8002/services/NetbarServices?wsdl
     */
    @Test
    public void cl3() {
        /** 使用本地wsdl
        URL url=null;
        try {
            url = new URL("http://localhost:8002/services/NetbarServices?wsdl");
        }catch (Exception e){

        }
         NetbarServices_Service factory= new NetbarServices_Service(url);
         */
        //NetbarServices_Service 服务端定义的serviceName，找到wsdl2java生成类中一个集成service的类，该类的实例可以作为工程使用
        NetbarServices_Service factory= new NetbarServices_Service();
        //调用Service子类的实例 getXXXPort方法，从而生成服务端实现类的实例
        NetbarServices ns = factory.getNetbarServicesImplPort();
        /**
         * 注意：需要修改生成的代码，引用类和SayHelloResponse中@XmlType(name = "sayHelloResponse1"
         */
        User user =setUser();

        //(一)调用服务端方法
        System.out.println(ns.sayHello(user));

    }

    @Test
    public void cl4() throws Exception {
        JaxWsDynamicClientFactory dcf = JaxWsDynamicClientFactory.newInstance();
        Client client = dcf.createClient(wsdlAddress);
        Endpoint endpoint = client.getEndpoint();


        // Make use of CXF service model to introspect the existing WSDL
        ServiceInfo serviceInfo = endpoint.getService().getServiceInfos().get(0);
        QName bindingName = new QName("http://api.service.study.platform.com", "NetbarServicesSoapBinding");
        BindingInfo binding = serviceInfo.getBinding(bindingName);
        QName opName = new QName("http://api.service.study.platform.com", "sayHello");
        BindingOperationInfo boi = binding.getOperation(opName); // Operation name is processOrder
        BindingMessageInfo inputMessageInfo = null;
        if (!boi.isUnwrapped()) {
            //OrderProcess uses document literal wrapped style.
            inputMessageInfo = boi.getWrappedOperation().getInput();
        } else {
            inputMessageInfo = boi.getUnwrappedOperation().getInput();
        }

        List<MessagePartInfo> parts = inputMessageInfo.getMessageParts();
        MessagePartInfo partInfo = parts.get(0); // Input class is Order

        // Get the input class Order
        Class<?> userClass = partInfo.getTypeClass();
        Object orderObject = userClass.newInstance();

        // Populate the user bean
        // set attribute
        PropertyDescriptor usernameProperty = new PropertyDescriptor("username", userClass);
        usernameProperty.getWriteMethod().invoke(orderObject, "ygf");
        PropertyDescriptor emailProperty = new PropertyDescriptor("email", userClass);
        emailProperty.getWriteMethod().invoke(orderObject, "I001@xxx.com");
        PropertyDescriptor gmtCreateProperty = new PropertyDescriptor("gmtCreate", userClass);
        gmtCreateProperty.getWriteMethod().invoke(orderObject, new Date());
        PropertyDescriptor userIdProperty = new PropertyDescriptor("userId", userClass);
        userIdProperty.getWriteMethod().invoke(orderObject, 999L);

        // Invoke the processOrder() method and print the result
        // The response class is String
        Object[] result = client.invoke(opName, orderObject);
        System.out.println("The order ID is " + result[0]);
    }

    User setUser(){
        User user = new User();
        user.setGmtCreate(dateToXmlDate(new Date()));
        user.setEmail("123@petrochina");
        user.setUserId(77L);
        user.setUsername("yue");
        return user;
    }

    /**
     * 将Date类转换为XMLGregorianCalendar
     *
     * @param date
     * @return
     */
    public XMLGregorianCalendar dateToXmlDate(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        DatatypeFactory dtf = null;
        try {
            dtf = DatatypeFactory.newInstance();
        } catch (DatatypeConfigurationException e) {
        }
        XMLGregorianCalendar dateType = dtf.newXMLGregorianCalendar();
        dateType.setYear(cal.get(Calendar.YEAR));
        // 由于Calendar.MONTH取值范围为0~11,需要加1
        dateType.setMonth(cal.get(Calendar.MONTH) + 1);
        dateType.setDay(cal.get(Calendar.DAY_OF_MONTH));
        dateType.setHour(cal.get(Calendar.HOUR_OF_DAY));
        dateType.setMinute(cal.get(Calendar.MINUTE));
        dateType.setSecond(cal.get(Calendar.SECOND));
        return dateType;
    }

}
